std::format
and std::vformat
have the same runtime behavior for well-formed format strings. The difference is exposed
when there is an error in the format string. For instance, if it contains an invalid format specifier:
-
std::vformat
throws a std::format_error
exception at runtime.
-
std::format
makes these mistakes ill-formed, causing the compilation to fail.
std::format
should be used whenever possible, allowing to catch malformed format strings early during the development process.
This rule raises an issue when std::vformat
is used with a constant string known at compile time.
Noncompliant code example
// Noncompliant, the string is known at compile time.
std::cout << std::vformat("{:.1f}", std::make_format_args(5.2f)) << std::endl;
// Noncompliant, the string is known at compile time.
constexpr std::string_view output_format = "{} {} {}";
std::cout << std::vformat(output_format, std::make_format_args(42, 52, 62)) << std::endl;
// Noncompliant
// The format specification does not match the type,
// throws `std::format_error` at run-time.
std::cout << std::vformat("{:d}", std::make_format_args(5.6f)) << std::endl;
// Noncompliant
// The number of formatted fields is greater than the number of arguments,
// throws `std::format_error` at run-time.
std::cout << std::vformat("{} {}", std::make_format_args("A string")) << std::endl;
Compliant solution
std::cout << std::format("{:.1f}", 5.2f) << std::endl; // Compliant
constexpr std::string_view output_format = "{} {} {}";
std::cout << std::format(output_format, 42, 52, 62) << std::endl; // Compliant
// Compile-time error, the format specification does not match the type.
// std::cout << std::format("{:d}", 5.6f) << std::endl;
// Compile-time error, the number of formatted fields is greater than the number of arguments.
// std::cout << std::format("{} {}", "A string") << std::endl;
Exceptions
This rule will not report the use of std::vformat
when its arguments are received by the enclosing function wrapped in a
std::format_args
object.
void log_internal (std::format_args const& args) {
assert(args.get(3));
std::cout << std::vformat("{} {}[{}]: {}", args);
}